#pragma once

//////////////////////////////////////////////////////////////////////////
template<typename A, typename B>
struct must_be_class_no_same
{
	must_be_class_no_same()
	{
		if(typeid(A).name() == typeid(B).name() )
		{
			assert(false);
		}
	}
};


//////////////////////////////////////////////////////////////////////////
template<typename D, typename B>
struct must_hase_base
{
	~must_hase_base()
	{
		void(*p)(D*, B*) = constraints;
	}
private:
	static void constraints(D* pD, B* pB)
	{
		pB = pD;
	}
};


//////////////////////////////////////////////////////////////////////////
template<typename T>
struct must_be_subscriptable
{
	~must_be_subscriptable()
	{
		T a;
		sizeof(a[0]);
	}
};


//////////////////////////////////////////////////////////////////////////
template<typename T>
struct must_be_pod
{
	~must_be_pod()
	{
		struct  
		{
			union 
			{
				T T_is_not_pod;
			};
		} a;
	}
};

template<>
struct must_be_pod<void>
{
	~must_be_pod()
	{
	}
};


//////////////////////////////////////////////////////////////////////////
template<typename T>
struct size_of
{
	enum 
	{
		value = sizeof(T)
	};
};

template<>
struct size_of<void>
{
	enum
	{
		value = 0
	};
};


template<typename T1, typename T2>
struct must_be_same_size
{
	must_be_same_size()
	{
		const int same_size = size_of<T1>::value == size_of<T2>::value ? 1:0;
		int i[same_size];
		UNREFERENCED_PARAMETER(i);
	}
};

